package com.demo.test;

import java.util.UUID;

/**
 *  COMB(combine) 改进 UUID
 *  COMB 型可以理解为一种改进的GUID。
 *  由于GUID数据毫无规律可言造成索引效率低下，影响了系统的性能，因此COMB将GUID和系统时间进行组合，以使其在索引和检索上有更优的性能。
 */
@SuppressWarnings("serial")
public final class COMB implements java.io.Serializable, Comparable<COMB> {

	private final long time;
	private final UUID uuid;
	

    private final long mostSigBits;
    private final long leastSigBits;

	// Constructors and Factories

	/*
	 * Private constructor which uses a UUID to construct the new COMB.
	 */
	private COMB(UUID uuid) {
		this.uuid=uuid;
		this.time = System.currentTimeMillis();

        this.mostSigBits = uuid.getMostSignificantBits();
        this.leastSigBits = uuid.getLeastSignificantBits();
	}

	/**
	 * 参照 UUID 对应方法
	 */
	public COMB(long mostSigBits, long leastSigBits, long time) {
		this.uuid=new UUID(mostSigBits, leastSigBits);
		this.time = time;

        this.mostSigBits = uuid.getMostSignificantBits();
        this.leastSigBits = uuid.getLeastSignificantBits();
	}

	/**
	 * 参照 UUID 对应方法
	 */
	public static COMB randomCOMB() {
		return new COMB(UUID.randomUUID());
	}

	/**
	 * 参照 UUID 对应方法
	 */
	public static COMB fromUUID(UUID uuid) {
		return new COMB(uuid);
	}

	public UUID getUuid() {
		return uuid;
	}

	public long getTime() {
		return time;
	}

	/**
	 * 参照 UUID 对应方法
	 */
	public int version() {
		return uuid.version();
	}

	/**
	 * 参照 UUID 对应方法
	 */
	public int variant() {
		return uuid.variant();
	}


    /**
	 * 参照 UUID 对应方法
     */
	public long timestamp() {
		if (version() != 1) { throw new UnsupportedOperationException("Not a time-based COMB"); }

		return (mostSigBits & 0x0FFFL) << 48 | ((mostSigBits >> 16) & 0x0FFFFL) << 32 | mostSigBits >>> 32;
	}


    /**
	 * 参照 UUID 对应方法
     */
	public int clockSequence() {
		if (version() != 1) { throw new UnsupportedOperationException("Not a time-based COMB"); }

		return (int) ((leastSigBits & 0x3FFF000000000000L) >>> 48);
	}


    /**
	 * 参照 UUID 对应方法
     */
	public long node() {
		if (version() != 1) { throw new UnsupportedOperationException("Not a time-based COMB"); }

		return leastSigBits & 0x0000FFFFFFFFFFFFL;
	}

	/**
	 * 参照 UUID 对应方法
	 */
	public String toString() {
        return (digits(mostSigBits >> 32, 8) + "-" +
                digits(mostSigBits >> 16, 4) + "-" +
                digits(mostSigBits, 4) + "-" +
                digits(leastSigBits >> 48, 4) + "-" +
                digits(time, 12));
    }
	
	/** Returns val represented by the specified number of hex digits. */
	private static String digits(long val, int digits) {
		long hi = 1L << (digits * 4);
		return Long.toHexString(hi | (val & (hi - 1))).substring(1);
	}
	
	/**
	 * 参照 UUID 对应方法
	 */
    public int hashCode() {
        long hilo = mostSigBits ^ leastSigBits ^ time;
        return ((int)(hilo >> 32)) ^ (int) hilo;
    }

	/**
	 * 参照 UUID 对应方法
	 */
    public boolean equals(Object obj) {
        if ((null == obj) || (obj.getClass() != COMB.class))
            return false;
        COMB id = (COMB)obj;
        return (mostSigBits == id.mostSigBits &&
                leastSigBits == id.leastSigBits &&
                time == id.time);
    }

    // Comparison Operations

	/**
	 * 参照 UUID 对应方法
	 */
    public int compareTo(COMB val) {
        return (this.mostSigBits < val.mostSigBits ? -1 :
                (this.mostSigBits > val.mostSigBits ? 1 :
                 (this.leastSigBits < val.leastSigBits ? -1 :
                  (this.leastSigBits > val.leastSigBits ? 1 :
                   (this.time > val.time ? 1 :0)))));
    }

}
